package com.cencat.order.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.common.result.Result;
import com.cencat.order.dto.RouteDTO;
import com.cencat.order.service.RouteService;
import com.cencat.order.vo.RouteVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 路线控制器
 * 
 * @author cencat
 * @date 2024-01-20
 */
@Slf4j
@RestController
@RequestMapping("/api/route")
@RequiredArgsConstructor
@Tag(name = "路线管理", description = "路线信息管理相关接口")
public class RouteController {

    private final RouteService routeService;

    @GetMapping("/page")
    @Operation(summary = "分页查询路线列表", description = "根据条件分页查询路线信息")
    public Result<IPage<RouteVO>> getRoutePage(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Long size,
            @Parameter(description = "路线名称") @RequestParam(required = false) String routeName,
            @Parameter(description = "路线编号") @RequestParam(required = false) String routeCode,
            @Parameter(description = "起点城市") @RequestParam(required = false) String startCity,
            @Parameter(description = "终点城市") @RequestParam(required = false) String endCity,
            @Parameter(description = "路线状态") @RequestParam(required = false) Integer routeStatus,
            @Parameter(description = "路线类型") @RequestParam(required = false) String routeType,
            @Parameter(description = "优先级") @RequestParam(required = false) Integer priority,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        log.info("分页查询路线列表，参数：current={}, size={}, routeName={}, routeCode={}, startCity={}, endCity={}, routeStatus={}, routeType={}, priority={}, startTime={}, endTime={}",
                current, size, routeName, routeCode, startCity, endCity, routeStatus, routeType, priority, startTime, endTime);
        
        Page<RouteVO> page = new Page<>(current, size);
        IPage<RouteVO> result = routeService.getRoutePage(page, routeName, routeCode, startCity, endCity,
                routeStatus, routeType, priority, startTime, endTime);
        
        return Result.success(result);
    }

    @GetMapping("/code/{routeCode}")
    @Operation(summary = "根据路线编号查询", description = "根据路线编号查询路线详细信息")
    public Result<RouteVO> getByRouteCode(
            @Parameter(description = "路线编号") @PathVariable String routeCode) {
        
        log.info("根据路线编号查询路线信息，routeCode={}", routeCode);
        
        RouteVO route = routeService.getByRouteCode(routeCode);
        if (route == null) {
            return Result.error("路线不存在");
        }
        
        return Result.success(route);
    }

    @GetMapping("/cities")
    @Operation(summary = "根据城市查询路线", description = "根据起点和终点城市查询路线")
    public Result<List<RouteVO>> getByCities(
            @Parameter(description = "起点城市") @RequestParam String startCity,
            @Parameter(description = "终点城市") @RequestParam String endCity,
            @Parameter(description = "路线状态") @RequestParam(required = false) Integer routeStatus,
            @Parameter(description = "路线类型") @RequestParam(required = false) String routeType,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        
        log.info("根据城市查询路线，startCity={}, endCity={}, routeStatus={}, routeType={}, limit={}",
                startCity, endCity, routeStatus, routeType, limit);
        
        List<RouteVO> routes = routeService.getByCities(startCity, endCity, routeStatus, routeType, limit);
        
        return Result.success(routes);
    }

    @GetMapping("/status/{routeStatus}")
    @Operation(summary = "根据状态查询路线", description = "根据路线状态查询路线列表")
    public Result<List<RouteVO>> getByStatus(
            @Parameter(description = "路线状态") @PathVariable Integer routeStatus,
            @Parameter(description = "路线类型") @RequestParam(required = false) String routeType,
            @Parameter(description = "优先级") @RequestParam(required = false) Integer priority,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "100") Integer limit) {
        
        log.info("根据状态查询路线列表，routeStatus={}, routeType={}, priority={}, startTime={}, endTime={}, limit={}",
                routeStatus, routeType, priority, startTime, endTime, limit);
        
        List<RouteVO> routes = routeService.getByStatus(routeStatus, routeType, priority, startTime, endTime, limit);
        
        return Result.success(routes);
    }

    @GetMapping("/type/{routeType}")
    @Operation(summary = "根据类型查询路线", description = "根据路线类型查询路线列表")
    public Result<List<RouteVO>> getByType(
            @Parameter(description = "路线类型") @PathVariable String routeType,
            @Parameter(description = "路线状态") @RequestParam(required = false) Integer routeStatus,
            @Parameter(description = "优先级") @RequestParam(required = false) Integer priority,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "100") Integer limit) {
        
        log.info("根据类型查询路线列表，routeType={}, routeStatus={}, priority={}, startTime={}, endTime={}, limit={}",
                routeType, routeStatus, priority, startTime, endTime, limit);
        
        List<RouteVO> routes = routeService.getByType(routeType, routeStatus, priority, startTime, endTime, limit);
        
        return Result.success(routes);
    }

    @GetMapping("/priority/{priority}")
    @Operation(summary = "根据优先级查询路线", description = "根据优先级查询路线列表")
    public Result<List<RouteVO>> getByPriority(
            @Parameter(description = "优先级") @PathVariable Integer priority,
            @Parameter(description = "路线状态") @RequestParam(required = false) Integer routeStatus,
            @Parameter(description = "路线类型") @RequestParam(required = false) String routeType,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "100") Integer limit) {
        
        log.info("根据优先级查询路线列表，priority={}, routeStatus={}, routeType={}, startTime={}, endTime={}, limit={}",
                priority, routeStatus, routeType, startTime, endTime, limit);
        
        List<RouteVO> routes = routeService.getByPriority(priority, routeStatus, routeType, startTime, endTime, limit);
        
        return Result.success(routes);
    }

    @GetMapping("/statistics")
    @Operation(summary = "路线统计信息", description = "获取路线相关统计数据")
    public Result<Map<String, Object>> getRouteStatistics(
            @Parameter(description = "路线状态") @RequestParam(required = false) Integer routeStatus,
            @Parameter(description = "路线类型") @RequestParam(required = false) String routeType,
            @Parameter(description = "优先级") @RequestParam(required = false) Integer priority,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
        
        log.info("查询路线统计信息，routeStatus={}, routeType={}, priority={}, startTime={}, endTime={}",
                routeStatus, routeType, priority, startTime, endTime);
        
        Map<String, Object> statistics = routeService.getRouteStatistics(routeStatus, routeType, priority, startTime, endTime);
        
        return Result.success(statistics);
    }

    @GetMapping("/planning")
    @Operation(summary = "路线规划", description = "根据起点终点进行路线规划")
    public Result<Map<String, Object>> routePlanning(
            @Parameter(description = "起点经度") @RequestParam BigDecimal startLongitude,
            @Parameter(description = "起点纬度") @RequestParam BigDecimal startLatitude,
            @Parameter(description = "终点经度") @RequestParam BigDecimal endLongitude,
            @Parameter(description = "终点纬度") @RequestParam BigDecimal endLatitude,
            @Parameter(description = "车辆类型") @RequestParam(required = false) String vehicleType,
            @Parameter(description = "货物重量") @RequestParam(required = false) BigDecimal cargoWeight,
            @Parameter(description = "货物体积") @RequestParam(required = false) BigDecimal cargoVolume,
            @Parameter(description = "优化类型") @RequestParam(defaultValue = "distance") String optimizeType) {
        
        log.info("路线规划，startLongitude={}, startLatitude={}, endLongitude={}, endLatitude={}, vehicleType={}, cargoWeight={}, cargoVolume={}, optimizeType={}",
                startLongitude, startLatitude, endLongitude, endLatitude, vehicleType, cargoWeight, cargoVolume, optimizeType);
        
        Map<String, Object> planningResult = routeService.routePlanning(startLongitude, startLatitude,
                endLongitude, endLatitude, vehicleType, cargoWeight, cargoVolume, optimizeType);
        
        return Result.success(planningResult);
    }

    @GetMapping("/optimization")
    @Operation(summary = "路线优化", description = "对现有路线进行优化分析")
    public Result<Map<String, Object>> routeOptimization(
            @Parameter(description = "路线ID") @RequestParam Long routeId,
            @Parameter(description = "优化类型") @RequestParam(defaultValue = "cost") String optimizeType,
            @Parameter(description = "约束条件") @RequestParam(required = false) String constraints) {
        
        log.info("路线优化，routeId={}, optimizeType={}, constraints={}", routeId, optimizeType, constraints);
        
        Map<String, Object> optimizationResult = routeService.routeOptimization(routeId, optimizeType, constraints);
        
        return Result.success(optimizationResult);
    }

    @GetMapping("/feasibility")
    @Operation(summary = "可行性分析", description = "分析路线的可行性")
    public Result<Map<String, Object>> feasibilityAnalysis(
            @Parameter(description = "路线ID") @RequestParam Long routeId,
            @Parameter(description = "车辆类型") @RequestParam(required = false) String vehicleType,
            @Parameter(description = "货物信息") @RequestParam(required = false) String cargoInfo,
            @Parameter(description = "时间窗口") @RequestParam(required = false) String timeWindow) {
        
        log.info("路线可行性分析，routeId={}, vehicleType={}, cargoInfo={}, timeWindow={}",
                routeId, vehicleType, cargoInfo, timeWindow);
        
        Map<String, Object> analysisResult = routeService.feasibilityAnalysis(routeId, vehicleType, cargoInfo, timeWindow);
        
        return Result.success(analysisResult);
    }

    @GetMapping("/risk-assessment")
    @Operation(summary = "风险评估", description = "评估路线的风险等级")
    public Result<Map<String, Object>> riskAssessment(
            @Parameter(description = "路线ID") @RequestParam Long routeId,
            @Parameter(description = "评估类型") @RequestParam(defaultValue = "comprehensive") String assessmentType,
            @Parameter(description = "历史数据天数") @RequestParam(defaultValue = "30") Integer historyDays) {
        
        log.info("路线风险评估，routeId={}, assessmentType={}, historyDays={}",
                routeId, assessmentType, historyDays);
        
        Map<String, Object> riskResult = routeService.riskAssessment(routeId, assessmentType, historyDays);
        
        return Result.success(riskResult);
    }

    @GetMapping("/cost-calculation")
    @Operation(summary = "成本计算", description = "计算路线的运输成本")
    public Result<Map<String, Object>> costCalculation(
            @Parameter(description = "路线ID") @RequestParam Long routeId,
            @Parameter(description = "车辆类型") @RequestParam(required = false) String vehicleType,
            @Parameter(description = "货物重量") @RequestParam(required = false) BigDecimal cargoWeight,
            @Parameter(description = "货物体积") @RequestParam(required = false) BigDecimal cargoVolume,
            @Parameter(description = "计算类型") @RequestParam(defaultValue = "standard") String calculationType) {
        
        log.info("路线成本计算，routeId={}, vehicleType={}, cargoWeight={}, cargoVolume={}, calculationType={}",
                routeId, vehicleType, cargoWeight, cargoVolume, calculationType);
        
        Map<String, Object> costResult = routeService.costCalculation(routeId, vehicleType, cargoWeight, cargoVolume, calculationType);
        
        return Result.success(costResult);
    }

    @GetMapping("/time-estimation")
    @Operation(summary = "时间预估", description = "预估路线的运输时间")
    public Result<Map<String, Object>> timeEstimation(
            @Parameter(description = "路线ID") @RequestParam Long routeId,
            @Parameter(description = "车辆类型") @RequestParam(required = false) String vehicleType,
            @Parameter(description = "交通状况") @RequestParam(defaultValue = "normal") String trafficCondition,
            @Parameter(description = "天气状况") @RequestParam(defaultValue = "normal") String weatherCondition) {
        
        log.info("路线时间预估，routeId={}, vehicleType={}, trafficCondition={}, weatherCondition={}",
                routeId, vehicleType, trafficCondition, weatherCondition);
        
        Map<String, Object> timeResult = routeService.timeEstimation(routeId, vehicleType, trafficCondition, weatherCondition);
        
        return Result.success(timeResult);
    }

    @PostMapping
    @Operation(summary = "创建路线", description = "创建新的路线信息")
    public Result<Boolean> createRoute(@Valid @RequestBody RouteDTO routeDTO) {
        log.info("创建路线，routeDTO={}", routeDTO);
        
        boolean result = routeService.createRoute(routeDTO);
        if (result) {
            return Result.success(true, "路线创建成功");
        } else {
            return Result.error("路线创建失败");
        }
    }

    @PutMapping("/{routeId}")
    @Operation(summary = "更新路线信息", description = "更新指定路线的信息")
    public Result<Boolean> updateRoute(
            @Parameter(description = "路线ID") @PathVariable Long routeId,
            @Valid @RequestBody RouteDTO routeDTO) {
        
        log.info("更新路线信息，routeId={}, routeDTO={}", routeId, routeDTO);
        
        boolean result = routeService.updateRoute(routeId, routeDTO);
        if (result) {
            return Result.success(true, "路线信息更新成功");
        } else {
            return Result.error("路线信息更新失败");
        }
    }

    @PutMapping("/{routeId}/status")
    @Operation(summary = "更新路线状态", description = "更新路线的状态")
    public Result<Boolean> updateRouteStatus(
            @Parameter(description = "路线ID") @PathVariable Long routeId,
            @Parameter(description = "路线状态") @RequestParam Integer routeStatus,
            @Parameter(description = "状态备注") @RequestParam(required = false) String statusRemark) {
        
        log.info("更新路线状态，routeId={}, routeStatus={}, statusRemark={}",
                routeId, routeStatus, statusRemark);
        
        boolean result = routeService.updateRouteStatus(routeId, routeStatus, statusRemark);
        if (result) {
            return Result.success(true, "路线状态更新成功");
        } else {
            return Result.error("路线状态更新失败");
        }
    }

    @PutMapping("/{routeId}/priority")
    @Operation(summary = "更新路线优先级", description = "更新路线的优先级")
    public Result<Boolean> updateRoutePriority(
            @Parameter(description = "路线ID") @PathVariable Long routeId,
            @Parameter(description = "优先级") @RequestParam Integer priority,
            @Parameter(description = "优先级备注") @RequestParam(required = false) String priorityRemark) {
        
        log.info("更新路线优先级，routeId={}, priority={}, priorityRemark={}",
                routeId, priority, priorityRemark);
        
        boolean result = routeService.updateRoutePriority(routeId, priority, priorityRemark);
        if (result) {
            return Result.success(true, "路线优先级更新成功");
        } else {
            return Result.error("路线优先级更新失败");
        }
    }

    @PutMapping("/{routeId}/cost")
    @Operation(summary = "更新路线成本", description = "更新路线的成本信息")
    public Result<Boolean> updateRouteCost(
            @Parameter(description = "路线ID") @PathVariable Long routeId,
            @Parameter(description = "基础成本") @RequestParam(required = false) BigDecimal baseCost,
            @Parameter(description = "燃油成本") @RequestParam(required = false) BigDecimal fuelCost,
            @Parameter(description = "过路费") @RequestParam(required = false) BigDecimal tollFee,
            @Parameter(description = "其他费用") @RequestParam(required = false) BigDecimal otherFee) {
        
        log.info("更新路线成本，routeId={}, baseCost={}, fuelCost={}, tollFee={}, otherFee={}",
                routeId, baseCost, fuelCost, tollFee, otherFee);
        
        boolean result = routeService.updateRouteCost(routeId, baseCost, fuelCost, tollFee, otherFee);
        if (result) {
            return Result.success(true, "路线成本更新成功");
        } else {
            return Result.error("路线成本更新失败");
        }
    }

    @PutMapping("/{routeId}/time-window")
    @Operation(summary = "更新时间窗口", description = "更新路线的时间窗口")
    public Result<Boolean> updateTimeWindow(
            @Parameter(description = "路线ID") @PathVariable Long routeId,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "HH:mm:ss") String startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "HH:mm:ss") String endTime,
            @Parameter(description = "工作日") @RequestParam(required = false) String workDays) {
        
        log.info("更新路线时间窗口，routeId={}, startTime={}, endTime={}, workDays={}",
                routeId, startTime, endTime, workDays);
        
        boolean result = routeService.updateTimeWindow(routeId, startTime, endTime, workDays);
        if (result) {
            return Result.success(true, "时间窗口更新成功");
        } else {
            return Result.error("时间窗口更新失败");
        }
    }

    @PutMapping("/batch/status")
    @Operation(summary = "批量更新路线状态", description = "批量更新多个路线的状态")
    public Result<Boolean> batchUpdateRouteStatus(
            @Parameter(description = "路线ID列表") @RequestParam List<Long> routeIds,
            @Parameter(description = "路线状态") @RequestParam Integer routeStatus) {
        
        log.info("批量更新路线状态，routeIds={}, routeStatus={}", routeIds, routeStatus);
        
        boolean result = routeService.batchUpdateRouteStatus(routeIds, routeStatus);
        if (result) {
            return Result.success(true, "批量更新路线状态成功");
        } else {
            return Result.error("批量更新路线状态失败");
        }
    }

    @DeleteMapping("/{routeId}")
    @Operation(summary = "删除路线", description = "软删除指定的路线信息")
    public Result<Boolean> softDeleteRoute(
            @Parameter(description = "路线ID") @PathVariable Long routeId) {
        
        log.info("软删除路线，routeId={}", routeId);
        
        boolean result = routeService.softDeleteRoute(routeId);
        if (result) {
            return Result.success(true, "路线删除成功");
        } else {
            return Result.error("路线删除失败");
        }
    }

    @DeleteMapping("/batch")
    @Operation(summary = "批量删除路线", description = "批量软删除多个路线信息")
    public Result<Boolean> batchSoftDeleteRoutes(
            @Parameter(description = "路线ID列表") @RequestParam List<Long> routeIds) {
        
        log.info("批量软删除路线，routeIds={}", routeIds);
        
        boolean result = routeService.batchSoftDeleteRoutes(routeIds);
        if (result) {
            return Result.success(true, "批量删除路线成功");
        } else {
            return Result.error("批量删除路线失败");
        }
    }

    @PutMapping("/{routeId}/restore")
    @Operation(summary = "恢复路线", description = "恢复已删除的路线信息")
    public Result<Boolean> restoreRoute(
            @Parameter(description = "路线ID") @PathVariable Long routeId) {
        
        log.info("恢复已删除的路线，routeId={}", routeId);
        
        boolean result = routeService.restoreRoute(routeId);
        if (result) {
            return Result.success(true, "路线恢复成功");
        } else {
            return Result.error("路线恢复失败");
        }
    }

    @GetMapping("/{routeId}/operation-logs")
    @Operation(summary = "查询操作日志", description = "查询路线的操作日志记录")
    public Result<List<Map<String, Object>>> getRouteOperationLogs(
            @Parameter(description = "路线ID") @PathVariable Long routeId,
            @Parameter(description = "操作类型") @RequestParam(required = false) String operationType,
            @Parameter(description = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "100") Integer limit) {
        
        log.info("查询路线操作日志，routeId={}, operationType={}, startTime={}, endTime={}, limit={}",
                routeId, operationType, startTime, endTime, limit);
        
        List<Map<String, Object>> logs = routeService.getRouteOperationLogs(routeId, operationType, startTime, endTime, limit);
        
        return Result.success(logs);
    }
}